import { debounce } from '@/utils'

/**
 * 通用的输入框tooltip hook
 * 自动检测文本是否溢出输入框，动态显示tooltip
 */
export function useInputTooltip() {
  // 存储所有需要检查tooltip的输入框
  const tooltipInputs = new Map<
    string,
    {
      inputRef: any
      shouldShow: any
      getValue: () => string
    }
  >()
  // 记录当前实例注册的所有key，用于自动清理
  const registeredKeys = new Set<string>()
  // 全局复用的测量span，避免重复创建
  let measureSpan: HTMLSpanElement | null = null

  /**
   * 获取或创建用于测量的span元素
   */
  const getMeasureSpan = (): HTMLSpanElement => {
    if (!measureSpan) {
      measureSpan = document.createElement('span')
      measureSpan.style.visibility = 'hidden'
      measureSpan.style.position = 'absolute'
      measureSpan.style.top = '-9999px'
      measureSpan.style.whiteSpace = 'nowrap'
      measureSpan.style.zIndex = '-1'
      document.body.appendChild(measureSpan)
    }
    return measureSpan
  }
  /**
   * 清理全局测量span
   */
  const cleanupMeasureSpan = () => {
    if (measureSpan && measureSpan.parentNode) {
      measureSpan.parentNode.removeChild(measureSpan)
      measureSpan = null
    }
  }
  /**
   * 检查文本是否溢出输入框
   */
  const checkTextOverflow = (element: HTMLElement, text: string): boolean => {
    if (!text || !element) return false
    try {
      // 获取输入框实际的input元素
      const inputElement = element.querySelector('.el-input__inner') || element.querySelector('input')
      if (!inputElement) return false
      const inputStyle = window.getComputedStyle(inputElement)
      // 使用全局复用的span测量文本宽度
      const tempSpan = getMeasureSpan()
      tempSpan.style.fontSize = inputStyle.fontSize
      tempSpan.style.fontFamily = inputStyle.fontFamily
      tempSpan.style.fontWeight = inputStyle.fontWeight
      tempSpan.style.letterSpacing = inputStyle.letterSpacing
      tempSpan.textContent = text
      const textWidth = tempSpan.offsetWidth
      // 获取输入框的实际可用宽度
      const inputRect = (inputElement as HTMLElement).getBoundingClientRect()
      const inputPaddingLeft = parseFloat(inputStyle.paddingLeft) || 0
      const inputPaddingRight = parseFloat(inputStyle.paddingRight) || 0

      // 动态获取后缀图标区域的宽度（包括清除按钮、密码显示按钮等）
      const suffixEl = element.querySelector('.el-input__suffix') as HTMLElement
      const reservedSpace = suffixEl ? suffixEl.offsetWidth - 8 : 8

      // 实际可用宽度 = 总宽度 - 左右padding - 后缀图标区域宽度
      const availableWidth = inputRect.width - inputPaddingLeft - inputPaddingRight - reservedSpace

      // 只有当文本明显超出时才显示tooltip（增加px容错）
      const shouldShow = textWidth > availableWidth + 15

      return shouldShow
    } catch (error) {
      console.error('检测文本溢出时出错:', error)
      return false
    }
  }

  /**
   * 检查单个输入框的tooltip状态
   */
  const checkSingleTooltip = (key: string) => {
    const input = tooltipInputs.get(key)
    if (!input) return
    const text = input.getValue()
    // 如果没有文本，直接隐藏tooltip
    if (!text || !input.inputRef.value) {
      input.shouldShow.value = false
      return
    }
    // 使用nextTick确保DOM更新完成
    nextTick(() => {
      try {
        const isOverflowing = checkTextOverflow(input.inputRef.value.$el, text)
        // 强制更新状态
        if (input.shouldShow.value !== isOverflowing) {
          input.shouldShow.value = isOverflowing
        }
      } catch (error) {
        console.error('检查tooltip时出错:', error)
        input.shouldShow.value = false
      }
    })
  }

  /**
   * 检查所有已注册的输入框tooltip状态
   */
  const checkAllTooltips = debounce(
    () => {
      tooltipInputs.forEach((_, key) => {
        checkSingleTooltip(key)
      })
    },
    100,
    false,
  )

  /**
   * 窗口大小变化处理
   */
  const handleResize = debounce(
    () => {
      checkAllTooltips()
    },
    150,
    false,
  )

  /**
   * 注册一个需要tooltip检查的输入框
   * @param key 唯一标识
   * @param getValue 获取输入框值的函数
   * @returns { inputRef, shouldShow, checkTooltip }
   */
  const registerInput = (key: string, getValue: () => string) => {
    const inputRef = ref()
    const shouldShow = ref(false)
    // 注册到map中
    tooltipInputs.set(key, {
      inputRef,
      shouldShow,
      getValue,
    })

    // 记录注册的key
    registeredKeys.add(key)

    // 检查当前输入框tooltip的函数
    const checkTooltip = debounce(
      () => {
        nextTick(() => checkSingleTooltip(key))
      },
      50,
      false,
    )
    return {
      inputRef,
      shouldShow,
      checkTooltip,
    }
  }

  /**
   * 注销输入框
   */
  const unregisterInput = (key: string) => {
    tooltipInputs.delete(key)
    registeredKeys.delete(key)
  }
  // 组件挂载时初始化
  onMounted(() => {
    window.addEventListener('resize', handleResize)
    // 初始检查所有tooltip
    nextTick(checkAllTooltips)
  })
  // 组件卸载时清理
  onUnmounted(() => {
    window.removeEventListener('resize', handleResize)
    // 清理当前实例注册的所有输入框
    registeredKeys.forEach((key) => {
      tooltipInputs.delete(key)
    })
    registeredKeys.clear()

    // 如果没有其他实例在使用，清理全局测量span
    if (tooltipInputs.size === 0) {
      cleanupMeasureSpan()
    }
  })
  return {
    registerInput,
    unregisterInput,
    checkAllTooltips,
    checkSingleTooltip,
  }
}
